package cli.menu;

/**
 * BudgetBuoy
 * 
 * Simplify your personal expense management
 * 
 * @team cs2103jan13-w15-3j
 */

//--------------------------------------------------------------

/**
 * AddExpense Class
 * 
 * Description: 
 * 
 * 
 * @package   cli.menu
 * @author    Lai Yong Quan (A0080909Y)
 * @edited by: Tan Si Ling (A0085314J)
 */
import shared.*;
import cli.tools.Process;

public class AddExpense extends Function{

	private static final String[] SELECT = {
		"-= Main menu > Add Entry > Expense =-",
		"[b]: back [u]: undo [r]: redo [h]: home menu",
	"Select a payment method: " };

	private static final String[] SELECTCAT = {
		"-= Main menu > Add Entry > Expense =-",
		"[b]: back [u]: undo [r]: redo [h]: home menu",
		"Select a category:"
	};

	private static final String[] ADDEXPENSE = {
		"-= Main menu > Add Entry > Expense =-",
		"[b]: back [u]: undo [r]: redo [h]: home menu",
		"",
		"Enter the information in the following format: ",
		"Name / Price / Date (DD.MM.YYYY, optional) / Description (optional)",
		"", "Input: " };

	private static final String[] PAYBYLOAN = {
		"-= Main menu > Add Entry > Expense =-",
		"[b]: back [u]: undo [r]: redo [h]: home menu",
		"",
		"Enter the information in the following format: ",
		"Name / Price of item / Lender / Date (DD.MM.YYYY, optional) / Description (optional)",
		"",
		"Input: "
	};


	private static final State BACK = State.ADDENTRYMENU;
	private static final State CURRENT = State.ADDEXPENSE;

	public static State runMenu() {

		//cli.print(SELECT);
		// need to check if result is null, desired object, or back
		Object choice = tools.selectFromList(cli.getApi().getModeList(),
				"Payment Mode", SELECT);
		cli.clearScreen();
		// if back signal sent
		if (choice == null) {
			return State.ADDENTRYMENU;
		}

		// if received Instruction object (divert to another menu)
		if (choice.getClass() == State.class) {
			return (State) choice;
		}

		// last case : if choice was really the correct object
		Mode paymentMode = (Mode) choice;

		// payment mode has not been selected, now to choose a category


		//cli.print(SELECTCAT);

		choice = tools.selectFromList(cli.getApi().getCategoryList(),
				"Category", SELECTCAT);
		cli.clearScreen();
		// if choice is not null, it is a re-direction to another menu screen
		if (choice == null) {
			return State.ADDENTRYMENU;
		}
		// if received Instruction object (divert to another menu)
		if (choice.getClass() == State.class) {
			return (State) choice;
		}
		// last case: category has been set
		Category category = (Category) choice;

		// if the payment mode is by Loan, go under special case
		if (paymentMode.getName().equalsIgnoreCase("Loan")) {
			return payByLoan(category);
		} else {
			// if it is a regular expense, prepare information to be called just
			// below
			return normalExpenseEntry(paymentMode, category);

		}

	}


	//function to handle payments by loan, require extra field of lender
	private static State payByLoan(Category category){
		boolean inputValid = false;
		String input;
	
		while (!inputValid) {
			cli.print(PAYBYLOAN);
			input = cli.nextLine();
			cli.clearScreen();
			// check if input is a hotkey
			if (input.length() == 1) {
				char charInput = input.charAt(0);
				if (tools.isHotKey(charInput)){
					return hotKeyFunction(charInput);
				}
			} else {
				inputValid = receiveLoanEntry(input, category);
				if(!inputValid){
					cli.println("Waiting for input for Loan entry...");
				}
			}
		//	cli.clearScreen();
			
		}
	

		return CURRENT;

	}


	// the boolean value indicates if there is a successful, error free entry
	public static boolean receiveLoanEntry(String input, Category category){

		int[] dmy = new int[3];
		String details = "";
		// process user input
		String[] processing = input.split("/");
		// checks if input is valid : at least 2 "attributes" - name and
		// price
		if (processing.length < 3){
			cli.print(INSUFFINFO);
			return false;
		}

		String name = processing[0];
		String price = processing[1];
		String lender = processing[2];
		// need to see if 3rd entry is date/details
		String unknown;
		// checks price for validity
		int amount = tools.Money2int(price);
		if (amount <= 0){
			cli.print(BADAMT);
			return false;
		}

		if (processing.length >= 4) {
			unknown = processing[3];

			try {
				dmy = tools.processDate(unknown);
			} catch (Exception e) {
				// means it is not a valid date
				cli.print(INVALIDDATE);
				dmy = tools.initDate();
				// treat 3rd entry as details
				details = unknown + " ";
			}


			// checks if there is a details section
			// since user may use '/' characters, we will treat anything
			// from
			// index 4 onwards as details
			if (processing.length >= 5) {
				for (int i = 4; i < processing.length; i++)
					details += processing[i] + " ";
			}

		}


		// now, input has been processed and treated to be passed to api
		try{
			Loan loan = cli.getApi().addItemLoan(name, amount, dmy[0], dmy[1], dmy[2], details,
					amount, category, lender);
			// Si Ling: **Keeping Track of the Actions DONE**
			tools.action.addToUndoStack(null, loan, Process.ADDITEMLOAN, null);
			// **END**
		}
		catch(Exception e){

			cli.print(ERROR);
			return false;
		}
		return true;
	}


	// method to handle receiving input for normal expense items
	private static State normalExpenseEntry(Mode paymentMode,
			Category category) {

		boolean inputValid = false;

		String input;

		while (!inputValid) {
			cli.print(ADDEXPENSE);
			input = cli.nextLine();
			cli.clearScreen();
			// check if input is a hotkey
			if (input.length() == 1) {
				char charInput = input.charAt(0);
				if (tools.isHotKey(charInput)){
					return hotKeyFunction(charInput);
				}
			} else {
				inputValid = receiveExpenseEntry(input, paymentMode, category);
			}
		}
		
		return CURRENT;

	}

	// the boolean value indicates if there is a successful, error free entry
	public static boolean receiveExpenseEntry(String input, Mode paymentMode,
			Category category) {

		// process user input
		String[] processing = input.split("/");
		int[] dmy = tools.initDate();

		// checks if input is valid : at least 2 "attributes" - name and price
		if (processing.length < 2) {
		
			cli.print(INSUFFINFO);
			return false;
		}

		String name = processing[0];
		String price = processing[1];
		// need to see if 3rd entry is date/details
		String unknown;
		String details = "";
		// checks price for validity

		int amount = tools.Money2int(price);

		// check for amt validity
		if (amount <= 0) {
			
			cli.print(BADAMT);
			return false;
		}
		if (processing.length >= 3) {
			unknown = processing[2];

			try {
				dmy = tools.processDate(unknown);
			} catch (Exception e) {
				// means it is not a valid date
				cli.print(INVALIDDATE);
				dmy = tools.initDate();
				// treat 3rd entry as details
				details = unknown + " ";
			}

			// checks if there is a details section
			// since user may use '/' characters, we will treat anything
			// from
			// index 3 onwards as details
			if (processing.length >= 4) {
				for (int i = 3; i < processing.length; i++)
					details += processing[i] + " ";
			}

		}

		// now, input has been processed and treated to be passed to api
		try {
			Expense expense = cli.getApi().addExpense(name, amount, dmy[0],
					dmy[1], dmy[2], details, paymentMode, category);
			// Si Ling: **Keeping Track of the Actions DONE**
			tools.action.addToUndoStack( null, expense,
					Process.ADDEXPENSE, null);
			// **END**
		} catch (Exception e) {
			
			cli.print(ERROR);
			return false;
		}

		return true;

	}

	private static State hotKeyFunction(char charInput) {

		State nextState = CURRENT;

		switch (charInput) {
		case 'b':
		case 'B':
			nextState = BACK;
			break;
		case 'u':
		case 'U':
			tools.undo();
			break;
		case 'r':
		case 'R':
			tools.redo();
			break;
		case 'h':
		case 'H':
			nextState = State.MAINMENU;
			break;
		default:
			break;
		}

		return nextState;

	}

}